package luo.hui.jiang.sort;

import java.util.Arrays;

/**
 * @author 罗惠江
 * @version 1.0
 * @email 1511619294@qq.com
 * @date 2020/8/1 15:37
 */
public class RadixSort {
    public static void main(String[] args) {
        int[] arr = new int[8];
        for (int i = 0; i < 8; i++) {
            arr[i] = (int) (Math.random() * 80000000);
        }
        long startTime = System.currentTimeMillis();
        radixSort2(arr);
        long endTime = System.currentTimeMillis();
        System.out.println("程序运行时间： " + (endTime - startTime) + "ms");
        System.out.println(Arrays.toString(arr));
    }

    // 基数排序方法
    public static void radixSort(int[] arr) {
        // 根据前面的推导过程，我们可以得到最终的技术排序代码
        // 1.得到数组中最大的数的位数
        int max = arr[0]; // 假设第一数就是最大数
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        // 得到最大数的几位数
        int maxLength = (max + "").length();
        // 定义 一个二维数组，表示10个桶，每个桶就是一个一维数组
        // 1.二维数组包含10个一维数组
        // 2.为了防止在入数的时候，数据溢出，每个数组，大小为arr.length
        // 3. 基数排序是典型的空间换时间的经典算法
        int[][] bucket = new int[10][arr.length];
        // 为了记录每个桶中，实际存放了多少数据，我们定义一个一维数组来记录各个桶的每次放入的数据个数
        int[] bucketElementCounts = new int[10];

        // 这里我们使用循环将代码处理
        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
            // 针对每个元素的对应位进行排序处理，第一次是各位，第二次是十位，。。。。
            for (int j = 0; j < arr.length; j++) {
                // 取出每个元素的对应位的值
                int digitOfElement = arr[j] / n % 10;
                // 放入到对应桶中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
                bucketElementCounts[digitOfElement]++;
            }
            // 按照这个桶的顺序（一维数组的下标依次取出数据，放入原来的数组中）
            int index = 0;
            // 遍历每一个桶中，并将桶中的数据放到原来的数组中
            for (int k = 0; k < bucketElementCounts.length; k++) {
                // 如果桶中，有数据，我们才会放到原数组
                if (bucketElementCounts[k] != 0) {
                    // 循环该桶即第k个桶，放入
                    for (int j = 0; j < bucketElementCounts[k]; j++) {
                        arr[index++] = bucket[k][j];
                    }
                }
                bucketElementCounts[k] = 0;
            }
        }
    }

    public static void radixSort1(int[] arr) {
        /*
        int max2 = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > max2) {
                max2 = arr[i];
            }
        }
        int maxLength2 = (max2 + "").length();
        int[][] bucket2 = new int[10][arr.length];
        int[] bucketElement2 = new int[10];
        for (int i = 0, n = 1; i < maxLength2; i++, n *= 10) {
            for (int j = 0; j < arr.length; j++) {
                int dif2 = arr[j] / n % 10;
                bucket2[dif2][bucketElement2[dif2]] = arr[j];
                bucketElement2[dif2]++;
            }
            int index = 0;
            // 遍历每一个桶中，并将桶中的数据放到原来的数组中
            for (int k = 0; k < bucketElement2.length; k++) {
                // 如果桶中，有数据，我们才会放到原数组
                if (bucketElement2[k] != 0) {
                    // 循环该桶即第k个桶，放入
                    for (int j = 0; j < bucketElement2[k]; j++) {
                        arr[index++] = bucket2[k][j];
                    }
                }
                bucketElement2[k] = 0;
            }
        }


    }*/

        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        int maxLength = (max + "").length();
        int[][] bucket = new int[10][arr.length];
        int[] bucketElementCounts = new int[10];
        for (int o = 0, n = 1; o < maxLength; o++, n *= 10) {
            for (int j = 0; j < arr.length; j++) {
                int digitOfElement = arr[j] / n % 10;
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
                bucketElementCounts[digitOfElement]++;
            }
            int index = 0;
            for (int k = 0; k < bucketElementCounts.length; k++) {
                if (bucketElementCounts[k] != 0) {
                    for (int j = 0; j < bucketElementCounts[k]; j++) {
                        arr[index++] = bucket[k][j];
                    }
                }
                bucketElementCounts[k] = 0;
            }
        }


    }

    public static void radixSort2(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (max < arr[i]) {
                max = arr[i];
            }
        }

        int maxLeangth = (max+"").length();
        int[][] bucket = new int[10][arr.length];
        int[] bucketElementCounts = new int[10];
        for (int i = 0,n=1; i < maxLeangth; i++,n*=10) {
            for (int j = 0; j < arr.length; j++) {
                int digitOfElement = arr[j]/n%10;
                bucket[digitOfElement][bucketElementCounts[digitOfElement]]=arr[j];
                bucketElementCounts[digitOfElement]++;
            }
            int index = 0;
            for (int j = 0; j < bucketElementCounts.length; j++) {
                if (bucketElementCounts[j]>0){
                    for (int k = 0; k < bucketElementCounts[j]; k++) {
                        arr[index++] = bucket[j][k];
                    }
                }
                bucketElementCounts[j] = 0;
            }
        }
    }

}
